<?php
namespace my;

class AlipayWap
{
    private $config,$puclicdata,$filtParam=[];

    /**
     * 初始化
     * @param array $config 
     *  $config['partner'] 开发者编号
     *  string $config['alipay_public_key'] 支付宝公钥文件
     *  string $config['private_key'] 证书私钥
     *  string $config['seller_id']  卖家账号
     *  string $config['notify_url'] 页面通知地址[禁止带get参数]
     *  string $config['sign_type'] 加密类型:md5|rsa MD5加密必需传md5key,rsa必需传alipay_public_key与private_key
     *  $config['jump_url'] 跳转URL
     */
    function __construct($config=array())
    {
        $this->config=array(
			'partner'				=>	'2088721142454730',
			'sign_type'				=>	'RSA',
			'input_charset'			=>	strtolower('UTF-8'),
			'seller_id'				=>	'wuguodong@hstwkj.com',
			'alipay_public_key'		=>	'alipay_public_key.pem',
			'private_key'	=>	'tw_private_key.pem',
			'jump_url'				=>	'https://mapi.alipay.com/gateway.do?',
            'notify_url'            =>  '',
            'return_url'            =>  '',
            'md5key'                =>  '',
		);
        
        //加密时需要过滤的参数
        $this->filtParam=["sign","sign_type"];
        
        //加载配置 noticeUrl
        $this->config($config);
      
    }
    
    /**
     * 设置生成加密串需要忽略的参数
     * @param array $Param
     */
    public function filt_Param($Param=[]){
        if(gettype($Param)=="array" && count($Param)>0)
        {
            $this->filtParam=array_merge($this->filtParam,$Param);
        }
    }
    
    
    /**
     * 设置配置
     * @param array $config 
     *  $config['partner'] 开发者编号
     *  string $config['alipay_public_key'] 支付宝公钥文件
     *  string $config['private_key'] 证书私钥
     *  string $config['seller_id'] 卖家账号
     *  string $config['notify_url'] 页面通知地址[禁止带get参数]
     *  string $config['sign_type'] 加密类型:md5|rsa MD5加密必需传md5key,rsa必需传alipay_public_key与private_key
     *  string $config['jump_url'] 跳转URL
     */
    public function config($config=array())
    {
        if(gettype($config) && count($config)>0){
                foreach($config as $key=>$val)
                {
                    if(array_key_exists($key,$this->config) && gettype($val)=="string" && $val!=''){
                        $this->config[$key]=(string)$val;
                    }
                }
         }
         $this->puclicdata=array();
         $this->publicdata();
    }
    
    /**
     * 成功返回
     */
    public function success()
    {
        return "success";
    }
    
    /**
     * 成功返回
     */
    public function error()
    {
        return "error";
    }
    
    
    /**
     * 发起支付
     * @param number $money 支付的金额以元为单位，精确到分
     * @param string $subject 产品名称
     * @param string $orderno 订单号
     * @param string $comments 备注
     */
    public function pay($money=0,$orderno='',$subject='消费',$comments="消费")
    {       
        $data= array(
            'service'				=>	'alipay.wap.create.direct.pay.by.user',
            'out_trade_no'			=>	$orderno,
            'subject'				=>	$subject,
            'payment_type'			=>	'1',
            'seller_id'				=>	$this->config['seller_id'],
            'total_fee'				=>	$money,
            'body'					=>	$comments,
            'it_b_pay'              =>  '15m',
        );
        $data= array_merge($data,$this->publicdata);
        
        $data['sign']				=	$this->sign($data);
        
        return [
            'type'=>'url',
            'data'=>$this->config['jump_url']. $this->bulid_param($data,true),
        ];
      
    }
    
    /**notice**
     *开始通知
     */
    public function notice()
    {
        //com_log([$_REQUEST],'alipay');
        $data=array(
            "code"=>1, #0|成功，1|有错误
            'msg'=>'success', #返回给第三方的信息
            'data'=>array(
                'out_trade_no'=>'', #要处理的订单号
                'total_fee'=>0, #用户支付的金额
                'buy_info'=>'', #打款用户的微信呢称
                'pay_data'=>'',#第三方订单号
            ),
        );
        
        $data= $_REQUEST;
        $sign= isset($data['sign'])?$data['sign']:'';
        
        if(count($data)==0){
            $data['msg']="参数不完整";
            return $data;
        }
        
        //通知校验
        if($this->notice_check())
        {
            if($this->g('trade_status')!='' && $this->g('out_trade_no')!='' && $this->g('total_fee')!='')
            {
                //开始业务处理
                if($this->g('trade_status')=='TRADE_SUCCESS')
                {
                    $data['code']=0;
                    $data['data']['out_trade_no']=$this->g("out_trade_no");
                    $data['data']['total_fee']=$this->g("total_fee");
                    $data['data']['buy_info']=$this->g("buyer_email");
                    $data['data']['pay_data']=json_encode($_REQUEST,JSON_UNESCAPED_UNICODE);
                }
            }
            else
            {
                $data['msg']= 'trade_status,out_trade_no,total_fee其中一项为空';
            }
        }
        else
        {
            $data['msg']="签名错误";
        }
       
        
        return $data;
    }
    
    /**
     * 加载支付插件配置
     */
    private function publicdata()
    {
        
        $this->publicdata=array(
            'partner'			=>	$this->config['partner'],
            'input_charset'		=>	$this->config['input_charset'],
            'sign_type'			=>	$this->config['sign_type'],
            'sign'				=>	'',
            'notify_url'		=>	$this->config['notify_url'],
            'return_url'        =>  $this->config['return_url'],
            'it_b_pay'          =>  '15m',
        );
    }
    
    
    /**
     * 通知效验
     * @param array $data
     * @param $sign 要验证的签名
     */
    private function notice_check($data=array(),$sign='')
    {
        $data=$this->filt_arg($data);
        $str= $this->bulid_param($data);
        
        if($str!='')
        {
            switch($this->config['sign_type'])
            {
                case "MD5":
                    $result=($sign==md5($str.$this->config['md5key']));
                    break;
                default:
                    $result=$this->rsaVerify($str,$this->config['alipay_public_key'],$sign);
                    break;
            }
            return $result;
        }
        return false;
    }
    
    
    /**生成签名
     * @param string $data
     * @param string $keyfile
     * @return string
     */
    private function sign($data)
    {        
        
        $data=$this->filt_arg($data);
        $str= $this->bulid_param($data);
        
        if($str!='')
        {
            switch($this->config['sign_type'])
            {
                case "MD5":
                    $str= md5($str.$this->config['md5key']);
                    break;
                default:
                    $str= $this->rsaSign($str);
                    break;
            }
        }
        return $str;
    }
    
    /**RSA-私钥加密
     * @param $data
     * @param string $keyfile
     * @return string
     */
    private function rsaSign($data,$keyfile='')
    {
        if($keyfile=='') $keyfile=__DIR__.'/rsa/'.$this->config['private_key'];
        $priKey = file_get_contents($keyfile);
        $res = openssl_get_privatekey($priKey);
        openssl_sign($data, $sign, $res);
        openssl_free_key($res);
        //base64编码
        return base64_encode($sign);
    }
    
    
    /**
     * 准备参与签名的数组
     * @param array $data
     */
    private function filt_arg($data=array())
    {
        //参数过滤
        if(count($this->filtParam)>0)
        {
            foreach($this->filtParam as $key=>$val)
            {
                if(isset($data[$val])) unset($data[$val]);
            }
        }
        return $data;
    }
    
    
    
    /**组装参数
     * @param array $data 传入的字符
     * @return string 返回值
     */
    private function bulid_param($data=array(),$urlencode=false)
    {
        $str='';
        ksort($data);
        reset($data);
        foreach($data as $key=>$val)
        {
            if(gettype($val)!='array' && $val!='')
            {
                if($str!='') $str.="&";
                $str.="$key=".($urlencode?urlencode($val):$val);
            }
        }
        return $str;
    }
    
    
    /**
     * 获取返回时的签名验证结果
     * @param $para_temp 通知返回来的参数数组
     * @param $sign 返回的签名结果
     * @return 签名验证结果
     */
    private function getSignVeryfy($para_temp, $sign)
    {
        $para_temp=$this->filt_arg($para_temp);
        $para_temp = $this->bulid_param($para_temp);
        return $this->rsaVerify($para_temp, trim($this->config['alipay_public_key']), $sign);
    }
    
    
    /** RSA验签
     * @param  $data 待签名数据
     * @param $ali_public_key_path 支付宝的公钥文件路径
     * @param $sign 要校对的的签名结果
     * @return 验证结果
     */
    private function rsaVerify($data, $ali_public_key_path, $sign)
    {
        $pubKey = file_get_contents($ali_public_key_path);
        $res = openssl_get_publickey($pubKey);
        $result = (bool)openssl_verify($data, base64_decode($sign), $res);
        openssl_free_key($res);
        return $result;
    }
    
    
    
    /**
     * 获取传的值
     * @param string $key
     * @param string $default
     */
    private function g($key="",$default="")
    {
        $val=isset($_REQUEST[$key])?$_REQUEST[$key]:$default;
    }
    
    
    
    
}